﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;

namespace Soft.Service
{
    /// <summary>
    /// 定时调度器
    /// </summary>
	public class TimedScheduling : ErrorResponse, IServerControl, IDisposable
    {
        ~TimedScheduling()
        {
            this.Dispose();
        }
      

        /// <summary>
        /// 是否被终结
        /// </summary>
        public bool Terminated
        {
            get
            {
                return this.mTerminated;
            }
            set
            {
                if (this.mTerminated && !value)
                {
                    this.Stop();
                }
            }
        }


        /// <summary>
        /// 服务状态
        /// </summary>
        public ServerState State { get; private set; } = ServerState.Stopped;


        /// <summary>
        /// 服务名称
        /// </summary>
        public string ServiceName { get; private set; } = "TimedScheduling";


        /// <summary>
        /// 添加需要被调度的任务
        /// </summary>
        /// <param name="task"></param>
        public void AddTask(SchedulingTask task)
        {
            if (!this.mTimer.Enabled)
            {
                this.mTasks.Add(task);
                task.Error += this.OnError;
            }
        }


        /// <summary>
        /// 释放服务
        /// </summary>
        public void Dispose()
        {
            this.Stop();
        }


        /// <summary>
        /// 启动服务
        /// </summary>
        /// <returns></returns>
        public Result Start()
        {
            if (this.State == ServerState.Stopped || this.State == ServerState.Error)
            {
                this.State = ServerState.Starting;
                if (this.mTasks.Count > 0)
                {
                    this.mTimer.Elapsed += this.MTimer_Elapsed;
                    this.mTimer.Start();
                    this.State = ServerState.Started;
                }
                else
                {
                    this.OnError("There are no tasks to run.");
                    this.State = ServerState.Stopped;
                }
            }
            return new Result();
        }


        /// <summary>
        /// 定时器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            DateTime dateTime = DateTime.Now;
            //循环需要调度的任务，每个任务开一个后台线程处理，这样不会阻塞，任务需要自己加锁防止并发
            this.mTasks.ForEach(delegate (SchedulingTask task)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(this.ExecuteTask), new TimedScheduling.ExecuteParam
                {
                    Task = task,
                    Now = dateTime
                });
            });
        }


        /// <summary>
        /// 执行任务
        /// </summary>
        /// <param name="state"></param>
        private void ExecuteTask(object state)
        {
            TimedScheduling.ExecuteParam executeParam = (TimedScheduling.ExecuteParam)state;
            if (executeParam.Task.TaskInfo.RepeatMode == ScheduleRepeatMode.Custom && executeParam.Task.TaskInfo.Cycle == TimeUnitItem.Empty)
            {
                return;
            }
            executeParam.Task.TryRun(executeParam.Now);
        }


        /// <summary>
        /// 停止服务
        /// </summary>
        public void Stop()
        {
            if (this.State == ServerState.Started)
            {
                this.State = ServerState.Stopping;
                this.mTimer.Stop();
                this.mTimer.Elapsed -= this.MTimer_Elapsed;
                for (; ; )
                {
                    if (!this.mTasks.Exists((SchedulingTask e) => e.Running))
                    {
                        break;
                    }
                    Thread.Sleep(200);
                }
                this.State = ServerState.Stopped;
            }
        }


        void AddError(ErrorEventHandle value)
        {
            base.Error += value;
        }


        void  RemoveError(ErrorEventHandle value)
        {
            base.Error -= value;
        }


        /// <summary>
        /// 是佛被终结
        /// </summary>
        private bool mTerminated = true;


        /// <summary>
        /// 定时器   500毫秒轮询一次任务执行
        /// </summary>
        private System.Timers.Timer mTimer = new System.Timers.Timer(500.0);


        /// <summary>
        /// 需要被调度的任务集合
        /// </summary>
        private List<SchedulingTask> mTasks = new List<SchedulingTask>();


        /// <summary>
        /// 执行的参数
        /// </summary>
        private struct ExecuteParam
        {

            /// <summary>
            /// 被调度的任务
            /// </summary>
            public SchedulingTask Task;

            /// <summary>
            /// 调度的时间
            /// </summary>
            public DateTime Now;

        }




    }
}
